/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.architexa.org.eclipse.gef.editpolicies;

import com.architexa.org.eclipse.gef.EditPart;
import com.architexa.org.eclipse.gef.EditPartListener;
import com.architexa.org.eclipse.gef.Request;
import com.architexa.org.eclipse.gef.RequestConstants;

/**
 * A GraphicalEditPolicy that is sensitive to the host's selection. The overall selection
 * of the host EditPart includes whether or not it has focus.  Subclasses will typically
 * decorate the GraphicalEditPart with things like selection handles and/or focus
 * feedback.
 * <P>
 * This EditPolicy adds itself as an {@link EditPartListener} so that it can observe
 * selection. When selection or focus changes, the EditPolicy will update itself and call
 * the appropriate methods.
 * 
 * @author hudsonr
 * @since 2.0
 */
public abstract class SelectionEditPolicy
	extends com.architexa.org.eclipse.gef.editpolicies.GraphicalEditPolicy
{

private EditPartListener selectionListener;
private int state = -1;
boolean focus;

/**
 * Extends activate to hook the appropriate listener and to initialize the visual changes
 * for representing selection/focus.
 * @see com.architexa.org.eclipse.gef.EditPolicy#activate()
 */
public void activate() {
	super.activate();
	addSelectionListener();
	setSelectedState(getHost().getSelected());
	setFocus(getHost().hasFocus());
}

/**
 * Adds an EditPartListener to the host to observe selection/focus changes.
 */
protected void addSelectionListener() {
	selectionListener = new EditPartListener.Stub() {
		public void selectedStateChanged(EditPart part) {
			setSelectedState(part.getSelected());
			setFocus(part.hasFocus());
		}
	};
	getHost().addEditPartListener(selectionListener);
}

/**
 * Extends deactivate to unhook the seleciton listener and to remove the visual
 * changes for representing selection/focus.
 * @see com.architexa.org.eclipse.gef.EditPolicy#deactivate()
 */
public void deactivate() {
	removeSelectionListener();
	setSelectedState(EditPart.SELECTED_NONE);
	setFocus(false);
	super.deactivate();
}

/**
 * @see com.architexa.org.eclipse.gef.EditPolicy#getTargetEditPart(Request)
 */
public EditPart getTargetEditPart(Request request) {
	if (RequestConstants.REQ_SELECTION.equals(request.getType()))
		return getHost();
	return null;
}

/**
 * Override to hide focus
 * @see #showFocus()
 */
protected void hideFocus() { }

/**
 * Override to hide selection
 */
protected abstract void hideSelection();

/**
 * Removes the EditPartListener used to observe selection
 */
protected void removeSelectionListener() {
	getHost().removeEditPartListener(selectionListener);
}

/**
 * Sets the internal focus value. This method is called automatically by the listener. If
 * the focus value is changed, either {@link #showFocus()} or {@link #hideFocus()} will be
 * called.
 * @param value <code>true</code> if the EditPolicy should show focus
 */
protected void setFocus(boolean value) {
	if (focus == value)
		return;
	focus = value;
	if (focus)
		showFocus();
	else
		hideFocus();
}

/**
 * Sets the internal selection value. This method is called automatically by the listener.
 * If the selection value is changed, the appropriate method is called to show the
 * specified selection type.
 * @param type the type of selection the EditPolicy should display
 */
protected void setSelectedState(int type) {
	if (state == type)
		return;
	state = type;
	if (type == EditPart.SELECTED_PRIMARY)
		showPrimarySelection();
	else if (type == EditPart.SELECTED)
		showSelection();
	else
		hideSelection();
}

/**
 * Override to show focus.
 * @see #hideFocus()
 */
protected void showFocus() { }

/**
 * Calls {@link #showSelection()} by default. Override to distinguish between primary and
 * normal selection.
 */
protected void showPrimarySelection() {
	showSelection();
}

/**
 * Override to show selection
 */
protected abstract void showSelection();
}


